package main

/// https://systembash.com/a-simple-go-tcp-server-and-tcp-client/
// this go exec file is for test purpose, will act as GPRS model in IFMS

import (
	"bufio"
	"fmt"
	"net"
	// "os"

	"time"
)

var (
	//
	// data_category []int8 = []int8{1, 3, 4, 5, 6}

	// data_body = map[int8]string{1: "1,2,3,4,5,6,12345678", 3: "3,4,5,6,7"}

	num = make(chan int)
)

// const (
// 	// MAXDEVCT           = 10240 // max 99999
// 	sla_msec int64 = 1000 // if deply time reach this porint, then we stop load test.
// )

func init() {
	go func() {
		for i := 0; ; i++ {
			num <- i
		}
	}()
}

func GetUniq() int {
	return <-num
}

type Device struct {
	conn         net.Conn
	incoming     chan string
	outgoing     chan string
	reader       *bufio.Reader
	writer       *bufio.Writer
	quiting      chan bool
	quitAnnounce bool
	device_id    string
	create_dt    time.Time
	elapsed      float64
	send_ct      int64
}

func CreateDevice(conn net.Conn) *Device {

	reader := bufio.NewReader(conn)
	writer := bufio.NewWriter(conn)
	// device_id := fmt.Sprintf("BENCHMARK_%05d", GetUniq())
	device_id := fmt.Sprintf("%v_BMRK_%04d", DevNamePrefix, GetUniq())
	device := &Device{
		conn:         conn,
		incoming:     make(chan string, 2),
		outgoing:     make(chan string),
		quiting:      make(chan bool),
		quitAnnounce: false,
		reader:       reader,
		writer:       writer,
		device_id:    device_id,
	}
	device.Listen()

	logger.Printf("Device [%v] created and listen started.\n", device_id)

	return device

}

func (self *Device) Listen() {
	go self.Read()
	go self.Write()
}

func newDevice(remoteAddr string, stat chan InstancePorf) *Device {
	conn, err := net.Dial("tcp", remoteAddr)

	if err != nil {
		logger.Printf("Dial fail: %s\n", err.Error())
		return nil
	}
	// defer conn.Close()
	device := CreateDevice(conn)
	// var loop_ct int64 = 0
	// var elapsed int64 = 0
	go func() {
		// defer conn.Close()
		loop_t0 := time.Now()
		for {
			select {

			case <-device.quiting:
				return

			default:

				loop_t0 = time.Now()

				text := fmt.Sprintf(`#;%v;1;1,2,3,4,5,6,%v;`, device.device_id, device.send_ct)

				logger.Printf(" <<< Msg : %v \n", text)
				device.outgoing <- text

				device.send_ct++
				time.Sleep(10 * time.Microsecond)

				retMsg := <-device.incoming

				device.elapsed += time.Since(loop_t0).Seconds()
				avgElapsed := device.elapsed / float64(device.send_ct)

				stat <- InstancePorf{device.send_ct, device.elapsed}

				logger.Printf("  >>> Msg: %v , avg elapsed:%v\n", retMsg, avgElapsed)

				time.Sleep(time.Second * MsgInterval)
			}

		}

	}()

	return device
}

func (self *Device) Read() {
	for !self.quitAnnounce {
		if line, _, err := self.reader.ReadLine(); err == nil {
			self.incoming <- string(line)
		} else {
			logger.Printf("Device[%v] Read error: %s\n", self.device_id, err)
			self.quit()
			return
		}

	}

}

func (self *Device) Write() {
	for data := range self.outgoing {
		if self.quitAnnounce {
			continue
		}
		if _, err := self.writer.WriteString(data + "\n"); err != nil {
			self.quit()
			return

		}
		if err := self.writer.Flush(); err != nil {
			logger.Printf("Device[%v] Write error: %s\n", self.device_id, err)
			self.quit()
			return
		}

	}
}

func (self *Device) quit() {
	self.quiting <- true
	time.Sleep(5 * time.Microsecond)
	self.quitAnnounce = true
	if self.conn != nil {
		self.conn.Close()

	}
}
